/*Group 04
José Renato da Silva Bonatelli 7288964
Matheus Martins Teixeira 7277482
Rafael de Paula Pinto Paravia 71522567*/

/*Calculating pi with a parallel approach of the Monte Carlo algorithm*/
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#define totalPoints 1E+9
#define numThreads 50

unsigned int *pointIsInsideCircle(void* i)
{
    unsigned int k = (unsigned int) i;
    unsigned int begin = k*totalPoints/numThreads;
    unsigned int end = (k==(numThreads-1))?totalPoints:(k+1)*totalPoints/numThreads;
    unsigned int count = 0;
    unsigned int r = time(NULL)+k;
    const unsigned int A = 1664525, C = 1013904223;
    float x,y;
    for(k=begin; k<end; k++){
        r = r*A+C;              /*Calculating a pseudo-random value*/
        x = (float)r/UINT_MAX;  /*Pseudo-random value between 0 and 1*/
        r = r*A+C;
        y = (float)r/UINT_MAX;
        if (x*x+y*y <=1)        /*Testing if the point (x,y) is inside the circle x^2+y^2=1*/
            count++;            /*Counting the number of points inside the circle*/
    }
    pthread_exit((void*)count); /*Exiting and returning count*/
}

int main(void)
{
    unsigned int i,aux;
    unsigned int pointsInCircle=0;
    int returnValue;
    void *ret;
    pthread_t threads[numThreads];
    for(i=0; i<numThreads; i++){
        /*Each thread receives a fraction of the total of points(10^9) and calculates how many of them are inside the circle*/
        returnValue = pthread_create(&threads[i], NULL, pointIsInsideCircle,(void * ) i); /*Starting the thread*/
        if (returnValue){   /*Error checking*/
            perror("Error :");
            exit(-1);
        }
    }
    for(i=0; i<numThreads; i++){
        /*Loop to finish the threads and to calculate the total number of points inside the circle*/
        pthread_join(threads[i], &ret);
        aux = (unsigned int*) ret;
        pointsInCircle+=aux;
    }
    printf("%.6f\n",(float)(pointsInCircle<<2)/totalPoints); /*Pi = 4*CircleArea/SquareArea*/
    pthread_exit(NULL);
    return 0;
}

